﻿#pragma once
#include <functional>
#ifdef USE_JEMALLOC
#include <jemalloc/jemalloc.h>
#endif

#include <utility>



namespace as
{
	namespace tools
	{

		class MemoryLog
		{
		public:
			MemoryLog();
			MemoryLog(std::function<void(size_t, size_t)> cb);
			~MemoryLog();

			void Tick();
		private:
			size_t beg_ = 0;
			std::function<void(size_t, size_t)> cb_;
		};

		template<class T>
		class MemoryAlloc
		{
		public:
			//这里using给底层用的
			using value_type = T;
			using pointer = T *;
			using const_pointer = const T *;
			using reference = T &;
			using const_reference = const T &;

			MemoryAlloc()noexcept {};
			MemoryAlloc(const MemoryAlloc<T> &)noexcept {};
			MemoryAlloc &operator=(const MemoryAlloc<T> &)noexcept {};

			template<class U>
			MemoryAlloc(const MemoryAlloc<U> &)noexcept {};
			template<class U>
			MemoryAlloc &operator=(const MemoryAlloc<U> &)noexcept {};

			~MemoryAlloc() {};

			virtual pointer allocate(size_t n = 1)
			{
#ifdef USE_JEMALLOC
				return static_cast<pointer>(je_malloc(sizeof(T) * n));
#else
				return static_cast<pointer>(malloc(sizeof(T) * n));
#endif
			}

			virtual void deallocate(T *p, size_t N = 1)
			{
#ifdef USE_JEMALLOC
				je_free(p);
#else
				free(p);
#endif
			}

			template<class U, class... Args>
			void construct(U *ptr, Args&&... args)
			{
				::new ((void *)ptr) U(std::forward<Args>(args)...);
			}

			template<class U>
			void destory(U *ptr, size_t n)
			{
				ptr->~U();
			}

			virtual size_t max_size()const noexcept
			{
				return sizeof(T) * 1024 * 1024 * 1024;
			}

			pointer address(reference x) const noexcept { return std::addressof(x); }
			const_pointer address(const_reference x) const noexcept { return std::addressof(x); }
		};

		template<class T1, class T2>
		constexpr bool operator==(const MemoryAlloc<T1> &lhs, const MemoryAlloc<T2> &rhs) {
			return true;
		}

		template<class T1, class T2>
		constexpr bool operator!=(const MemoryAlloc<T1> &lhs, const MemoryAlloc<T2> &rhs) {
			return false;
		}

	}
}

